package com.zxy.day0624_util.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D.Float;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Random;
import javax.imageio.ImageIO;

/**
 * @Auther: lenovo
 * @Date: 2021/9/27 20:52
 * @Description:
 */
public class QRCodeUtils {
    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "JPG";
    private static final int QRCODE_SIZE = 300;
    private static final int WIDTH = 60;
    private static final int HEIGHT = 60;

    public QRCodeUtils() {
    }

    private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = (new MultiFormatWriter()).encode(content, BarcodeFormat.QR_CODE, 300, 300, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, 1);

        for(int x = 0; x < width; ++x) {
            for(int y = 0; y < height; ++y) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? -16777216 : -1);
            }
        }

        if (imgPath != null && !"".equals(imgPath)) {
            insertImage(image, imgPath, needCompress);
            return image;
        } else {
            return image;
        }
    }

    private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
        File file = new File(imgPath);
        if (!file.exists()) {
            System.err.println("" + imgPath + "   该文件不存在！");
        } else {
            Image src = ImageIO.read(new File(imgPath));
            int width = ((Image)src).getWidth((ImageObserver)null);
            int height = ((Image)src).getHeight((ImageObserver)null);
            if (needCompress) {
                if (width > 60) {
                    width = 60;
                }

                if (height > 60) {
                    height = 60;
                }

                Image image = ((Image)src).getScaledInstance(width, height, 4);
                BufferedImage tag = new BufferedImage(width, height, 1);
                Graphics g = tag.getGraphics();
                g.drawImage(image, 0, 0, (ImageObserver)null);
                g.dispose();
                src = image;
            }

            Graphics2D graph = source.createGraphics();
            int x = (300 - width) / 2;
            int y = (300 - height) / 2;
            graph.drawImage((Image)src, x, y, width, height, (ImageObserver)null);
            Shape shape = new Float((float)x, (float)y, (float)width, (float)width, 6.0F, 6.0F);
            graph.setStroke(new BasicStroke(3.0F));
            graph.draw(shape);
            graph.dispose();
        }
    }

    public static String encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
        BufferedImage image = createImage(content, imgPath, needCompress);
        mkdirs(destPath);
        String file = (new Random()).nextInt(99999999) + ".jpg";
        ImageIO.write(image, "JPG", new File(destPath + "/" + file));
        return file;
    }

    public static void mkdirs(String destPath) {
        File file = new File(destPath);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }

    }

    public static void encode(String content, String imgPath, String destPath) throws Exception {
        encode(content, imgPath, destPath, false);
    }

    public static void encode(String content, String destPath, boolean needCompress) throws Exception {
        encode(content, (String)null, (String)destPath, needCompress);
    }

    public static void encode(String content, String destPath) throws Exception {
        encode(content, (String)null, (String)destPath, false);
    }

    public static void encode(String content, String imgPath, OutputStream output, boolean needCompress) throws Exception {
        BufferedImage image = createImage(content, imgPath, needCompress);
        ImageIO.write(image, "JPG", output);
    }

    public static void encode(String content, OutputStream output) throws Exception {
        encode(content, (String)null, (OutputStream)output, false);
    }

    public static String decode(File file) throws Exception {
        BufferedImage image = ImageIO.read(file);
        if (image == null) {
            return null;
        } else {
            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Hashtable<DecodeHintType, Object> hints = new Hashtable();
            hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
            Result result = (new MultiFormatReader()).decode(bitmap, hints);
            String resultStr = result.getText();
            return resultStr;
        }
    }

    public static String decode(String path) throws Exception {
        return decode(new File(path));
    }

    public static void main(String[] args) throws Exception {
        String text = "http://www.baidu.com";
        String logoPath = "d:\\pic\\8af9965b-3479-49e7-9796-4084ad581a5f908.jpg";
        String destPath = "d:\\QR_code\\test.jpg";
        System.out.println(encode(text, logoPath, destPath, true));
    }
}
